# mtl_parser.py

"""
MTL (Material Template Library) 文件解析器模块
============================================

此模块提供用于解析 .mtl 文件的函数，主要提取材质的漫反射颜色(Kd)。
"""

from typing import Dict, List, Any

# 定义一个类型别名，让代码更清晰
# 表示一个材质字典，例如: {"Kd": [0.8, 0.8, 0.8], "d": 0.5}
MaterialProperties = Dict[str, Any]
# 表示所有材质的字典，例如: {"WallMaterial": MaterialProperties, ...}
MaterialDict = Dict[str, MaterialProperties]

def load_mtl(file_path: str) -> MaterialDict:
    """
    加载并解析 .mtl 文件，提取材质名称和属性。

    目前主要关注的属性:
    - newmtl material_name: 定义一个新材质的开始。
    - Kd r g b: 漫反射颜色 (Diffuse Color)，r,g,b为0-1之间的浮点数。
    - d alpha: 透明度 (dissolve)，alpha为0-1的浮点数。我们也会读取它以备后用。

    参数:
        file_path (str): .mtl 文件的路径。

    返回:
        MaterialDict: 一个字典，键是材质名称，值是包含该材质属性的另一个字典。
                      例如: {'WallMaterial': {'Kd': [0.8, 0.8, 0.8]}}
    """
    materials: MaterialDict = {}
    current_material_name: str | None = None

    try:
        with open(file_path, 'r', encoding='utf-8') as file:
            for line in file:
                line = line.strip()
                if not line or line.startswith('#'):
                    continue

                parts = line.split()
                if not parts:
                    continue
                
                command = parts[0]

                # 1. 遇到 'newmtl'，开始一个新的材质定义
                if command == 'newmtl':
                    if len(parts) > 1:
                        # 记录当前正在定义的材质名称
                        current_material_name = parts[1]
                        # 为这个新材质在字典中创建一个空条目
                        materials[current_material_name] = {}
                    else:
                        # 如果 newmtl 后面没有名字，这是个格式错误，但我们选择忽略它并继续
                        current_material_name = None

                # 2. 如果已经在一个材质定义中，解析其属性
                elif current_material_name:
                    if command == 'Kd': # 漫反射颜色
                        if len(parts) >= 4:
                            try:
                                # 使用列表推导式将颜色值字符串转换为浮点数
                                color = [float(c) for c in parts[1:4]]
                                materials[current_material_name]['Kd'] = color
                            except ValueError:
                                print(f"警告 (MTL解析): 无法解析颜色值在行: '{line}'")
                    
                    elif command == 'd': # 透明度
                        if len(parts) >= 2:
                            try:
                                alpha = float(parts[1])
                                materials[current_material_name]['d'] = alpha
                            except ValueError:
                                print(f"警告 (MTL解析): 无法解析透明度值在行: '{line}'")
                    
                    # 未来可以轻松在这里添加对其他属性(Ka, Ks, map_Kd等)的解析
                    # elif command == 'Ka':
                    #     ...
                    # elif command == 'map_Kd':
                    #     ...

    except FileNotFoundError:
        print(f"错误 (MTL解析): 材质文件 '{file_path}' 未找到。")
        return {} # 返回一个空字典
    except Exception as e:
        print(f"错误 (MTL解析): 解析文件 '{file_path}' 时发生意外错误: {e}")
        return {}

    return materials


# --- 模块独立测试代码 ---
if __name__ == "__main__":
    print("--- 开始独立测试 mtl_parser.py ---")

    # 创建一个临时的测试 .mtl 文件
    test_mtl_content = """
# 这是材质文件的注释
# 定义墙体材质
newmtl WallMaterial
Kd 0.8 0.8 0.8
d 1.0

# 空行和无效行

newmtl
f 1 2 3

# 定义玻璃材质，但颜色值有误
newmtl GlassMaterial
Kd 0.1 blue 0.8

# 定义木头材质
newmtl WoodMaterial
Ka 0.1 0.1 0.1 # 环境光，我们目前不解析
Kd 0.5 0.3 0.1 # 这是我们需要的颜色
Ks 0.9 0.9 0.9 # 高光，我们不解析
"""
    test_mtl_path = "test_parser.mtl"
    with open(test_mtl_path, 'w', encoding='utf-8') as f:
        f.write(test_mtl_content)

    print(f"已创建测试文件: {test_mtl_path}")

    # 调用解析函数
    parsed_materials = load_mtl(test_mtl_path)

    print("\n--- 解析结果 ---")
    import json
    # 使用json.dumps美化打印输出
    print(json.dumps(parsed_materials, indent=2))

    # --- 验证结果 ---
    print("\n--- 结果验证 ---")
    assert "WallMaterial" in parsed_materials, "未找到 WallMaterial"
    assert parsed_materials["WallMaterial"].get("Kd") == [0.8, 0.8, 0.8], "WallMaterial 颜色不正确"
    
    assert "GlassMaterial" in parsed_materials, "未找到 GlassMaterial"
    assert "Kd" not in parsed_materials["GlassMaterial"], "GlassMaterial 的错误颜色不应被解析"

    assert "WoodMaterial" in parsed_materials, "未找到 WoodMaterial"
    assert parsed_materials["WoodMaterial"].get("Kd") == [0.5, 0.3, 0.1], "WoodMaterial 颜色不正确"

    print("所有断言测试通过！")

    # 清理测试文件
    import os
    try:
        os.remove(test_mtl_path)
        print(f"\n已清理测试文件: {test_mtl_path}")
    except OSError as e:
        print(f"清理测试文件失败: {e}")

    print("--- mtl_parser.py 测试结束 ---")